package Exercises;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Instruction：
 * Author：@author MaLi
 */
public class Exercise01 {
    public static void main(String[] args) {
        DataBuffer<String> dataBuffer = new DataBuffer<>();
        ArrayList<Thread> threads = new ArrayList<>(8);
        AtomicInteger number = new AtomicInteger(0);
        //创建三个生产者
        for (int i = 0; i < 3; i++) {
            Thread producer = new Thread() {
                @Override
                public void run() {
                    while (true) {
                        dataBuffer.add(Thread.currentThread().getName() + " --- " + number.incrementAndGet());
                    }
                }
            };
            threads.add(producer);
        }
        //创建5个消费者
        for (int i = 0; i < 5; i++) {
            Thread consumer = new Thread() {
                @Override
                public void run() {
                    while (true) {
                        dataBuffer.get();
                    }
                }
            };
            threads.add(consumer);
        }
        // 启动所有生产者和消费者
        for (Thread thread : threads) {
            thread.start();
        }
        // MainThread等待生产者与消费者执行
        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private static class DataBuffer<T> {
        private int maxSize = 10;
        private List<T> container = new ArrayList<>();
        private AtomicInteger size = new AtomicInteger(0);
        private Object lock = new Object();

        //获取元素
        public T get() {

            while (true) {
                synchronized (lock) {
                    if (size.get() <= 0) {
                        try {
                            lock.notifyAll(); //唤醒其它线程
                            System.out.println("请生产者尽快生产...");
                            lock.wait();    //当前线程等待, 释放锁
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    } else {
                        T element = container.remove(0);
                        System.out.println(Thread.currentThread().getName() + "获取到元素: " + element);
                        size.decrementAndGet();//修改容量
                        return element;
                    }
                }
            }
        }

        //生产元素
        public void add(T t) {

            while (true) {
                synchronized (lock) {
                    if (size.get() >= maxSize) {
                        try {
                            lock.notifyAll(); //唤醒其它线程
                            System.out.println("请消费者尽快消费...");
                            lock.wait();    //当前线程等待, 释放锁
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    } else {
                        container.add(t);
                        System.out.println(Thread.currentThread().getName() + "生产了元素: " + t);
                        size.incrementAndGet();
                    }
                }
            }
        }
    }

    /*private static class Producer<T> extends Thread {
        private DataBuffer<T> dataBuffer;

        public void Producer(DataBuffer<T> dataBuffer) {
            this.dataBuffer = dataBuffer;
        }

        @Override
        public void run() {
            dataBuffer.add();
        }
    }*/
}
